<template>
    <div class="app-container">
        <div class="flex-head">
            <FormSearch
                ref="formSearchRef"
                :FormParams="queryParams"
                :FormRules="searchFormRules"
                :FormShow="showSearch"
                @submit="getList"
                @refresh="getList" />
            <el-row class="mb20">
                <el-col :span="16">
                    <el-button type="primary" @click="uploadDialog = true" icon="Upload">上传文件</el-button>
                    <el-button type="warning" :disabled="downloadDisabled" icon="Delete" @click="handleBatchDownload">批量下载</el-button>
                    <el-button type="danger" :disabled="disabled" icon="Delete" @click="handleBatchDelete">批量删除</el-button>
                </el-col>
                <el-col :span="6">
                    <div class="total">
                        <template v-if="currentUserActive">
                            <div class="total-all">总人数为 {{ peopleTotal }} 个</div>
                            <span>&nbsp;&nbsp;/&nbsp;&nbsp;</span>
                        </template>

                        <div class="total-current">当前页总人数为 {{ currentTotal }} 个</div>
                    </div>
                </el-col>
                <el-col :span="2">
                    <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
                </el-col>
            </el-row>
        </div>
        <TableBate
            id="tableBateId"
            ref="tableRef"
            :loading="loading"
            :TableHead="tableHead"
            :TableData="tableData"
            :TableAttrs="tableAttrs"
            @handleSelectionChange="handleSelectionChange"
            @handleActionBarEvent="handleActionBarEvent">
            <template #name="{ row }">
                <span>{{ row.touristList.map((item) => item.name).join('、') }}</span>
            </template>
            <template #status="{ row }">
                <template v-for="item in statusOptions">
                    <el-tag v-if="item.value == row.status" :type="item.elTagClass">{{ item.label }}</el-tag>
                </template>
            </template>
        </TableBate>
        <pagination
            id="pagination"
            v-show="total > 0"
            :total="total"
            v-model:page="queryParams.pageNumber"
            v-model:limit="queryParams.pageSize"
            @pagination="getList" />
        <el-dialog v-model="uploadDialog" title="上传文件" width="50vw" center>
            <FileUpload limit="100" fileSize="20" :fileType="['xlsx', 'xls']" :UploadPath="uploadPath" @handleUploadSuccess="uploadSuccessCallback" />
        </el-dialog>
        <el-dialog v-if="refundDialog" v-model="refundDialog" title="退票" width="40vw" center>
            <Refund :GroupUsers="groupUsers" @cancel="refundDialog = false" />
        </el-dialog>
    </div>
</template>

<script setup>
import FormSearch from '@/components/FormSearch/index.jsx'
import TableBate from '@/components/Table_Bate/index.jsx'
import FileUpload from '@/components/FileUpload'
import Refund from './refund.vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { searchFormRules, tableHead, statusOptions } from './config'
import { onMounted, reactive, ref, watch } from 'vue'
import { getGbTicket, DelGbTicket, UpdateRemark, outTicketTotal } from '@/api/gbTicket.js'
import { CanvasGenerateImage } from './index'
import JSZip from 'jszip'
import { saveAs } from 'file-saver'

const { proxy } = getCurrentInstance()

onMounted(() => {
    getList()
    authorityJudgment()
})

const formSearchRef = ref()
// 右侧工具栏是否显示
const showSearch = ref(true)
// 列表数据
const tableData = ref([])
const tableRef = ref()
const total = ref(0)
const loading = ref(false)
const currentTotal = ref(0)
const refundDialog = ref(false)
const peopleTotal = ref(0)
const disabled = ref(true)
const groupUsers = ref([])
const uploadDialog = ref(false)
const downloadDisabled = ref(true)
const multipleSelection = ref([])
const currentUserActive = ref(false)
const uploadPath = ref('/gbTicket/uploadExcel')

const data = reactive({
    queryParams: {
        pageNumber: 1,
        pageSize: 10,
        docNo: null,
        status: 1,
        name: null,
    },
    tableAttrs: {
        size: 'large',
        align: 'center',
    },
})

const { queryParams, tableAttrs, row } = toRefs(data)

watch(
    multipleSelection,
    (newMultipleSelection) => {
        disabled.value = !newMultipleSelection.length
        downloadDisabled.value = !newMultipleSelection.length
    },
    { deep: true },
)

// 权限判断
const authorityJudgment = () => {
    const userInfo = JSON.parse(localStorage.getItem('userInfo'))
    currentUserActive.value = userInfo.accountType === 1 ? true : false
    // 总人数
    outTicketTotal().then(({ result }) => {
        peopleTotal.value = result
    })
}
// 获取table数据
const getList = () => {
    loading.value = true
    getGbTicket(queryParams.value).then(({ result: res }) => {
        tableData.value = res.data
        const totals = tableData.value.map((item) => item.touristList.map((v) => v.length).length).reduce((total, currentV) => total + currentV, 0)
        total.value = res.total
        loading.value = false
        currentTotal.value = tableData.value
            .map((item) => item.touristList.length)
            .reduce((accumulator, currentValue) => accumulator + currentValue, 0)
    })
}

// 上传成功
const uploadSuccessCallback = () => {
    uploadDialog.value = false
    getList()
}

//批量删除
const handleBatchDelete = () => {
    const userIds = multipleSelection.value.map((item) => item.touristList.map((user) => user.id))
    handleDelete(userIds.flat())
}

const handleDelete = (ids) => {
    ElMessageBox.confirm(`确认要删除ID为${ids.join('、')}的数据项?`, '警告', {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning',
    })
        .then(() => {
            DelGbTicket(ids).then((res) => {
                ElMessage({
                    type: 'success',
                    message: '删除成功',
                })
                getList()
            })
        })
        .catch(() => {
            ElMessage({
                type: 'info',
                message: `取消删除`,
            })
        })
}

// 已选中的行数据
const handleSelectionChange = (data) => {
    multipleSelection.value = data
}
// 当前行下载图片
const handleActionBarEvent = (row, type) => {
    if (type === '下载') {
        handleDownload(row)
    }
    if (type === '删除') {
        handleSingleDelete(row)
    }
    if (type === '退票') {
        handleRefund(row)
    }
}
const handleRefund = (row) => {
    groupUsers.value = row.touristList
    refundDialog.value = true
}
// 删除单个
const handleSingleDelete = (row) => {
    const ids = row.touristList.map((item) => item.id)
    handleDelete(ids)
}

const base64ToBlob = (code) => {
    const parts = code.split(';base64,')
    const contentType = parts[0].split(':')[1]
    const raw = window.atob(parts[1])
    let rawLength = raw.length
    let uInt8Array = new Uint8Array(rawLength)
    for (let i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i)
    }
    return new Blob([uInt8Array], {
        type: contentType,
    })
}
// 批量下载
const handleBatchDownload = async () => {
    try {
        const unqualifiedRows = multipleSelection.value.filter((row) => [0, 2].includes(row.status))
        const unqualifiedGroupNames = unqualifiedRows.map((row) => row.groupIndex).join('、')
        if (unqualifiedRows.length) {
            return proxy.$modal.msgWarning(`${unqualifiedGroupNames}分组不符合图片生成规则，请选择《已抢到到票》的状态!`)
        }

        const zip = new JSZip()
        const Total = multipleSelection.value.map((item) => item.touristList.length).reduce((n, o) => n + o, 0)
        const Groupings = multipleSelection.value.map((item) => item.groupIndex)
        const zipName = `${Total}_${Groupings}`
        const folder = zip.folder(zipName)

        // 处理好处理返回promise对象
        const asyncFiles = await multipleSelection.value.map(async (row) => {
            // 生成图片返回promise对象
            const asyncImages = await generatePicture(row)
            // 行文件名称
            const rowName = row.touristList.map((item) => item.name).join('、')
            // 每行
            return new Promise(async (resolve) => {
                resolve({
                    name: rowName,
                    rowData: await asyncImages.map(async (item) => {
                        // 每个人
                        const { name, images, docNoEnd } = item
                        return {
                            fileName: name,
                            docNoEnd,
                            // 每个人里面的两张图
                            files: await Promise.all(images),
                        }
                    }),
                })
            })
        })

        // 创建文件夹 压缩下载
        Promise.all(asyncFiles).then(async (values) => {
            const data = await values.map(async (value) => {
                return {
                    rowData: await Promise.all(value.rowData),
                    rowName: await value.name,
                }
            })
            Promise.all(data).then((values) => {
                values.forEach((value) => {
                    const rowFolder = folder.folder(value.rowName)
                    value.rowData.forEach((item, index) => {
                        const personFile = rowFolder.folder(item.fileName + item.docNoEnd)
                        item.files.forEach((file) => {
                            personFile.file(`${file.name}.jpeg`, base64ToBlob(file.base64), { binary: true })
                        })
                    })
                })
                zip.generateAsync({
                    type: 'blob',
                }).then((content) => {
                    saveAs(content, `${zipName}.zip`)
                })
                proxy.$modal.closeLoading()
            })
        })
    } catch (error) {
        console.log(error, 'error')
    }
}
// 生成图片
const generatePicture = async (row) => {
    proxy.$modal.loading('生成图片中!')
    const res = await UpdateRemark()
    // 压缩包名字
    const zipFileName = row.touristList.map((item) => item.name).join('、')
    const users = row.touristList
    const asyncCanvas = []

    for (let i = 0; i < users.length; i++) {
        const item = users[i]

        const data = {
            // 手机号码
            iphoneNum: item.mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2'),
            // 入馆时间
            admissionTime: row.buyDate,
            // 订单编号
            orderNum: row.orderNumber,
            // 身份证号码
            docNum: item.docNo.replace(/(\w{3})\w+(\w{3})/, '$1************$2'),
            // 下单时间
            orderTime: JSON.parse(item.remark).payTime, //row.outTicketTime,
            // 金额
            orderAmount: '¥ 0.0',
            // 二维码数据
            qrCodeData: JSON.parse(item.remark).ticketNumber || '没有二维码数据',
            // 姓名
            name: item.name,
            // 位置
            location: '国家博物馆北门西侧入口',
            // 状态
            status: '待核验',
        }

        console.log(data, 'data');
        
        const canvasImage = new CanvasGenerateImage(data, row)
        asyncCanvas.push({
            name: item.name,
            docNoEnd: item.docNo.slice(-4),
            images: [canvasImage.createCanvas(), canvasImage.createCanvas2()],
        })
    }

    return asyncCanvas
}

// 下载按钮
const handleDownload = async (row) => {
    try {
        const asyncImages = await generatePicture(row)
        const zip = new JSZip()
        const asyncFiles = asyncImages.map((item) => {
            const { name, images, docNoEnd } = item
            return new Promise((resolve) => {
                let files = []
                Promise.all(images).then((values) => {
                    files = values.map((image) => {
                        return {
                            fileName: image.name,
                            filePath: image.base64,
                        }
                    })
                    resolve({
                        name,
                        images: files,
                        docNoEnd,
                    })
                })
            })
        })
        Promise.all(asyncFiles).then((values) => {
            values.forEach((item, index) => {
                const { images, name, docNoEnd } = item
                // 文件名称（一个姓名对应一个文件名称里面有2张图片
                const subFolder = zip.folder(name + docNoEnd)
                images.forEach((image) => {
                    subFolder.file(`${image.fileName}.jpeg`, base64ToBlob(image.filePath), { binary: true })
                })
            })

            zip.generateAsync({
                type: 'blob',
            }).then((content) => {
                saveAs(content, `${asyncImages.map((item) => item.name).join('、')}.zip`)
            })
            proxy.$modal.closeLoading()
        })
    } catch (error) {
        console.log(error, 'error')
    }
}
/**
 *
 * @param {随机数的数量} n
 * @param {随机数的最小值} min
 * @param {随机数的最大值} max
 * @returns {Set}
 */
function generateUniqueRandoms(n, min = 1000, max = 9999) {
    const randomSet = new Set()

    while (randomSet.size < n) {
        const randomNumber = Math.floor(Math.random() * (max - min + 1)) + min
        randomSet.add(randomNumber)
    }

    return [...randomSet]
}

// 压缩下载
const compressedDownload = () => {}
</script>
<style lang="scss" scoped>
.test {
    font-family: 'Source Han Serif', serif;
}
.total {
    font-size: 18px;
    color: #666;
    font-weight: bold;
    line-height: 32px;
    display: flex;
    justify-content: end;
    &-all {
        text-align: right;
    }
    &-current {
        text-align: right;
    }
}
</style>
